home *** CD-ROM | disk | FTP | other *** search
- #define LIBQTOOLS_CORE
- #include "../include/libqtools.h"
-
- /*
- * PAK-tools
- *
- * entryName == 0 -> OP_EXTRACT all
- * destDir == 0 -> OP_EXTRACT to current directory
- */
-
- /*
- *
- */
-
- bool CheckPAK(HANDLE pakFile, struct packheader *Header, bool newWad)
- {
- if (pakFile) {
- __lseek(pakFile, 0, SEEK_END);
- if (!__ltell(pakFile)) {
- if (newWad) {
- /*
- * file is new
- */
- Header->magic.integer = BigLong(MAGIC_PACK);
- Header->offset = LittleLong(sizeof(struct packheader));
-
- Header->size = LittleLong(0);
- __write(pakFile, Header, sizeof(struct packheader));
-
- return TRUE;
- }
- else
- return FALSE;
- }
- else {
- __lseek(pakFile, 0, SEEK_SET);
- __read(pakFile, Header, sizeof(struct packheader));
-
- return Header->magic.integer == BigLong(MAGIC_PACK) ? TRUE : FALSE;
- }
- }
- else
- return FALSE;
- }
-
- /*
- * findpak return ever one entry more than exists!
- */
- struct packentry *FindPAK(HANDLE pakFile, char *entryName, struct packheader *Header, struct packentry **Entry)
- {
- struct packentry *allEntries;
-
- __lseek(pakFile, LittleLong(Header->offset), SEEK_SET);
- if ((*Entry = allEntries = (struct packentry *)tmalloc(LittleLong(Header->size) + sizeof(struct packentry)))) {
- int i;
-
- __read(pakFile, allEntries, LittleLong(Header->size));
- if (entryName) {
- for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
- if (!fnmatch(entryName, allEntries->name, FNM_PATHNAME)) {
- /*
- * return offset of valid entry
- */
- return allEntries;
- }
- allEntries++;
- }
- }
- /*
- * not in pakfile
- */
- return 0;
- }
- else
- return (struct packentry *)-1;
- }
-
- struct packentry *SearchPAK(char *entryName, struct packheader *Header, struct packentry *allEntries)
- {
- int i;
-
- for (i = 0; i < (LittleLong(Header->size) / sizeof(struct packentry)); i++) {
- if (!fnmatch(entryName, allEntries->name, FNM_PATHNAME))
- return allEntries;
- allEntries++;
- }
- return 0;
- }
-
- bool ExtractPAK(HANDLE pakFile, FILE * script, char *destDir, char *entryName, unsigned char outType, operation procOper, bool recurse)
- {
- struct packheader Header;
- struct packentry *Entry, *allEntries;
- bool retval = FALSE;
-
- if (CheckPAK(pakFile, &Header, FALSE)) {
- /*
- * we assume that the dir is at the end of the file!!!!!
- */
- switch ((long int)(Entry = FindPAK(pakFile, entryName, &Header, &allEntries))) {
- case -1:
- eprintf(failed_memory, LittleLong(Header.size) + sizeof(struct packentry), "packentries");
- break;
- case 0:
- if ((entryName) && (*entryName != '\0')) {
- eprintf("no entry %s found in pak\n", entryName);
- break;
- }
- default:{
- int i, parseCount;
-
- parseCount = (LittleLong(Header.size) / sizeof(struct packentry));
-
- /* process only ONE (case 0:) */
- if (Entry) {
- i = Entry - allEntries;
- parseCount = i + 1;
- }
- /* reset and process ALL (default:) */
- else {
- i = 0;
- Entry = allEntries;
- }
-
- for (; i < parseCount; i++, Entry++) {
- char fileName[NAMELEN_PATH];
-
- __strncpy(fileName, destDir, NAMELEN_PATH - 1);
- __strncat(fileName, Entry->name, NAMELEN_PATH - 1);
-
- switch (procOper) {
- case OP_EXTRACT:{
- HANDLE fileDst;
-
- mprintf(oper_extract, Entry->name, fileName);
- CreatePath(fileName);
-
- if ((fileDst = __open(fileName, H_WRITE_BINARY)) > 0) {
- struct rawdata *rawData;
-
- __lseek(pakFile, LittleLong(Entry->offset), SEEK_SET);
- if ((rawData = GetRaw(pakFile, Entry->name, LittleLong(Entry->size)))) {
- retval = PutRaw(fileDst, rawData);
- rfree(rawData);
- /* processName at this point */
- if (recurse)
- retval = processName(fileName, 0, 0, outType, 0, 0, procOper, script ? TRUE : FALSE, recurse);
- }
- else
- eprintf(failed_memory, LittleLong(Entry->size), fileName);
- __close(fileDst);
- }
- else
- eprintf(failed_fileopen, fileName);
- }
- break;
- case OP_DELETE:{
- int diff, last;
-
- diff = LittleLong(Entry->size);
- last = LittleLong(Entry->offset);
-
- mprintf(oper_delete, Entry->name, fileName);
- /* delete from disk */
- __lseek(pakFile, last, SEEK_SET);
- if (CutOff(pakFile, diff, 0)) {
- int content;
-
- /* correct header */
- content = LittleLong(Header.size) / sizeof(struct packentry);
- Header.size = LittleLong(LittleLong(Header.size) - sizeof(struct packentry));
- Header.offset = LittleLong(LittleLong(Header.offset) - diff);
-
- /* delete from memlist */
- __memcpy(Entry, Entry + 1, LittleLong(Header.size));
- /* delete from loop */
- parseCount--;
- i--;
- Entry--;
-
- /* correct all following offsets */
- while (content--)
- /* correct all, that come afterwards */
- if (LittleLong(allEntries[content].offset) >= last)
- allEntries[content].offset = LittleLong(LittleLong(Entry->offset) - diff);
-
- /* dump header */
- __lseek(pakFile, 0, SEEK_SET);
- __write(pakFile, &Header, sizeof(struct packheader));
-
- /* dump entries */
- __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
- __write(pakFile, allEntries, LittleLong(Header.size));
- /* cut off removed entry */
- retval = CutOff(pakFile, sizeof(struct packentry), 0);
- }
- }
- break;
- case OP_LIST:
- case OP_DEFAULT:
- default:{
- mprintf("%54s %8d bytes (offset: %8x)\n", Entry->name, LittleLong(Entry->size), LittleLong(Entry->offset));
- retval = TRUE;
- }
- break;
- }
-
- if (script)
- fprintf(script, "update %s as %s as %c\n", fileName, Entry->name, 'P');
- }
- }
- break;
- }
- tfree(allEntries);
- }
- else
- eprintf("no valid pakfile\n");
-
- return retval;
- }
-
- bool AddPAK(struct palpic * inPic, struct rawdata * inData, char *pakName, operation procOper)
- {
- char *procName;
- HANDLE pakFile = __open(pakName, H_READWRITE_BINARY_OLD);
- struct packheader Header;
- struct packentry *Entry, *allEntries;
- bool retval = FALSE;
-
- if (pakFile < 0)
- pakFile = __open(pakName, H_READWRITE_BINARY_NEW);
-
- if (pakFile > 0) {
- if (CheckPAK(pakFile, &Header, TRUE)) {
- if (inPic) {
- procName = inPic->name;
- ReplaceExt(procName, "lmp");
- }
- else if (inData) {
- procName = inData->name;
- }
-
- /* we assume that the dir is at the end of the file!!!!! */
- switch ((long int)(Entry = FindPAK(pakFile, procName, &Header, &allEntries))) {
- case -1:
- eprintf(failed_memory, LittleLong(Header.size) + sizeof(struct packentry), "packentries");
- break;
- case 0:
- switch (procOper) {
- case OP_REPLACE:
- eprintf("no entry %s found to replace in pak %s\n", procName, pakName);
- break;
- case OP_UPDATE:
- mprintf(oper_update, Entry->name[0] ? Entry->name : procName, pakName);
- goto skip1;
- case OP_ADD:
- case OP_DEFAULT:
- default:
- mprintf(oper_add, Entry->name[0] ? Entry->name : procName, pakName);
- skip1:
- __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
- /* seek to end of data */
- Entry = allEntries + (LittleLong(Header.size) / sizeof(struct packentry));
- Entry->offset = Header.offset;
-
- if (inData)
- retval = PutRaw(pakFile, inData);
- else if (inPic)
- retval = PutLMP(pakFile, inPic);
- else
- eprintf("nothing to add\n");
-
- if (retval) {
- Entry->size = LittleLong(__ltell(pakFile) - LittleLong(Header.offset));
- __strncpy(Entry->name, procName, NAMELEN_PAK);
- Header.size = LittleLong(LittleLong(Header.size) + sizeof(struct packentry));
-
- Header.offset = LittleLong(__ltell(pakFile));
- /* write directory */
- if (__write(pakFile, allEntries, LittleLong(Header.size)) == LittleLong(Header.size)) {
- __lseek(pakFile, 0, SEEK_SET);
- /* write header */
- __write(pakFile, &Header, sizeof(struct packheader));
- }
- else
- retval = FALSE;
- }
- else
- eprintf(failed_filewritesize, procName, pakName);
- break;
- }
- tfree(allEntries);
- break;
- default:
- switch (procOper) {
- case OP_REPLACE:
- mprintf(oper_replace, Entry->name[0] ? Entry->name : procName, pakName);
- goto skip2;
- case OP_UPDATE:
- mprintf(oper_update, Entry->name[0] ? Entry->name : procName, pakName);
- skip2:{
- int diff, last, newsize;
-
- newsize = (inData ? inData->size : ((inPic->width * inPic->height) + sizeof(struct lump)));
-
- diff = LittleLong(Entry->size) - newsize;
- last = LittleLong(Entry->offset);
-
- __lseek(pakFile, last, SEEK_SET);
- if (diff > 0) {
- if (CutOff(pakFile, diff, 0))
- retval = TRUE;
- }
- else if (diff < 0) {
- if (PasteIn(pakFile, -diff, 0))
- retval = TRUE;
- }
-
- if (retval) {
- int content;
-
- __lseek(pakFile, last, SEEK_SET);
-
- if (inData)
- retval = PutRaw(pakFile, inData);
- else if (inPic)
- retval = PutLMP(pakFile, inPic);
-
- /* correct header */
- content = LittleLong(Header.size) / sizeof(struct packentry);
- Header.offset = LittleLong(LittleLong(Header.offset) - diff);
-
- /* correct all following offsets */
- while (content--)
- /* correct all, that come afterwards */
- if (LittleLong(allEntries[content].offset) >= last)
- allEntries[content].offset = LittleLong(LittleLong(Entry->offset) - diff);
-
- /* correct entry */
- Entry->size = LittleLong(newsize);
- Entry->offset = LittleLong(last);
-
- /* dump header */
- __lseek(pakFile, 0, SEEK_SET);
- __write(pakFile, &Header, sizeof(struct packheader));
-
- /* dump entries */
- __lseek(pakFile, LittleLong(Header.offset), SEEK_SET);
- __write(pakFile, &allEntries, LittleLong(Header.size));
- }
- }
- break;
- case OP_ADD:
- case OP_DEFAULT:
- default:
- eprintf("old entry %s found in pak %s\n", procName, pakName);
- break;
- }
- tfree(allEntries);
- break;
- }
- __close(pakFile);
- }
- else
- eprintf("no valid pakfile %s\n", pakName);
- }
- else
- eprintf(failed_fileopen, pakName);
-
- return retval;
- }
-